/* From: http://demo-effects.sourceforge.net */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#include <linux/fb.h>
#include <unistd.h>



static unsigned short pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0, tpos1, tpos2, tpos3, tpos4;
static int aSin[512];



static void plasma_init (void)
{
  int i;
  float rad;
 
  /*create sin lookup table */
  for (i = 0; i < 512; i++)
    {
      rad =  ((float)i * 0.703125) * 0.0174532; /* 360 / 512 * degree to rad, 360 degrees spread over 512 values to be able to use AND 512-1 instead of using modulo 360*/
      aSin[i] = sin(rad) * 1024; /*using fixed point math with 1024 as base*/
    }
}

void plasma (unsigned char *frame_buffer, int screen_width, int screen_height)
{
  unsigned short i,j;
  unsigned char index;
  int x;  

  
  plasma_init();
  
  /* time based demo loop */
  for (;;) 
  {
      /*this is where it all happens */

      /* draw plasma */

      tpos4 = pos4;
      tpos3 = pos3;
      
    unsigned char *fb = frame_buffer;  
      
    for (i = 0; i < screen_height; ++i)
	{
	  tpos1 = pos1 + 5;
	  tpos2 = pos2 + 3;
	  
	  tpos3 &= 511;
	  tpos4 &= 511;
	  
	  for (j = 0; j < screen_width; ++j)
	    {
	      tpos1 &= 511;
	      tpos2 &= 511;
	      
	      x = aSin[tpos1] + aSin[tpos2] + aSin[tpos3] + aSin[tpos4]; /*actual plasma calculation*/
	      
	      index = 128 + (x >> 4); /*fixed point multiplication but optimized so basically it says (x * (64 * 1024) / (1024 * 1024)), x is already multiplied by 1024*/
	      
	      /* magic transformation: color index to RGB24 */
	      *fb ++ = index + i;		/* blue */
	      *fb ++ = index + j;		/* green */
	      *fb ++ = index + i/2;		/* red */
	      *fb ++ = 0;		/* red */
	      
	      tpos1 += 5; 
	      tpos2 += 3; 
	    }
	  
	  tpos4 += 3;
	  tpos3 += 1;
	}
           
      /* move plasma */
      pos1 += 9;
      pos3 += 8;
      
      /* TODO: some delay */
      #if 0
      usleep(10 * 1000);
      #endif
    }

}

